package mjrg.game.frame;


import javax.sound.midi.MidiSystem;
import javax.sound.midi.Sequence;
import javax.sound.midi.Sequencer;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.*;
import java.util.Stack;

public class FiveChessFrame extends JFrame implements WindowListener {
  static final int WIDTH = 790, HEIGHT = 660; // 游戏窗口的高和宽
  FiveChessPanel fcp = null; // 游戏的实现类对象
  File data = null; // 存储记录的文件
  Sequencer sequencer; // 播发器
  Sequence sequence; // 音乐
  boolean play = false; // 是否播放
  int num; // 第几首
  Thread musicthread = null; // 播放歌曲的线程
  private String name;

  public FiveChessFrame(String s) // 构造函数
  {
    super(s);
    name = s;
    fcp = new FiveChessPanel(); // 初始化对象和读取数据
    readData();
    if (play) { // 如果上次设置为播放音乐则启动播放音乐线程
      try {
        sequencer = MidiSystem.getSequencer();
        sequencer.open();
      } catch (Exception e) {
        e.printStackTrace();
      }
      musicthread = new Thread(new MusicRun());
      musicthread.start();
    }
    createMenu(); // 创建菜单
    this.add(fcp);
    this.addMouseListener(fcp); // 添加鼠标监听
    this.setSize(WIDTH, HEIGHT);
    this.setLocation(250, 40);
    this.setVisible(true); // 窗口的参数设定
    addWindowListener(this);//添加窗口监听
    this.setDefaultCloseOperation(EXIT_ON_CLOSE);
    this.setResizable(false);
  }

  // 规划一个菜单
  public void createMenu() {
    JMenuBar jm = new JMenuBar(); // 菜单条
    /**
     *  菜单模式
     */
    JMenu model = new JMenu("   模式   ");
    final JCheckBoxMenuItem general = new JCheckBoxMenuItem(" 普通模式 ");
    final JCheckBoxMenuItem tompstone = new JCheckBoxMenuItem(" 墓碑模式 ");
    final JCheckBoxMenuItem landmine = new JCheckBoxMenuItem(" 地雷模式 ");
    if (fcp.tompstone)
      tompstone.setState(true); // 选择在哪个复选框内
    else if (fcp.landmine)
      landmine.setState(true);
    else
      general.setState(true);
    //普通模式
    general.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        general.setState(true); // 选择框的小勾变化
        tompstone.setState(false);
        landmine.setState(false);
        fcp.tompstone = false; // 标记模式的变量改变
        fcp.landmine = false;
        fcp.replay(); // 切换模式时重新开局
      }
    });
    //墓碑模式
    tompstone.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        general.setState(false);
        tompstone.setState(true);
        landmine.setState(false);
        fcp.tompstone = true;
        fcp.landmine = false;
        fcp.replay();
      }
    });
    //地雷模式
    landmine.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        general.setState(false);
        tompstone.setState(false);
        landmine.setState(true);
        fcp.tompstone = false;
        fcp.landmine = true;
        fcp.replay();
      }
    });
    model.add(general); // 菜单项添加到菜单
    model.add(tompstone);
    model.add(landmine);
    /**
     *  先后手
     */
    JMenu xianhou = new JMenu("   先后手   "); //设置先后手菜单
    final JCheckBoxMenuItem xianshou = new JCheckBoxMenuItem(" 先手");
    final JCheckBoxMenuItem houshou = new JCheckBoxMenuItem(" 后手 ");
    xianshou.setState(true);
    xianshou.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        xianshou.setState(true); // 选择框的小勾变化
        houshou.setState(false);
        fcp.replay(); // 切换模式时重新开局
      }
    });
    houshou.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        houshou.setState(true); // 选择框的小勾变化
        xianshou.setState(false);
        fcp.replay(); // 切换模式时重新开局
        int x = 3 + (int) (Math.random() * 1000) % 9;
        int y = 3 + (int) (Math.random() * 1000) % 9;
        fcp.chess[x][y] = fcp.computerchessnum;
      }
    });
    xianhou.add(xianshou); // 菜单项添加到菜单
    xianhou.add(houshou);

    JMenu saface = new JMenu("   外观   ");//设置外观菜单
    /**
     *  背景更换
     */
    JMenu background = new JMenu("  背景  ");
    final JCheckBoxMenuItem background1 = new JCheckBoxMenuItem("   背景1  ");
    final JCheckBoxMenuItem background2 = new JCheckBoxMenuItem("   背景2  ");
    final JCheckBoxMenuItem background3 = new JCheckBoxMenuItem("   背景3  ");
    JMenuItem background_n = new JMenuItem("  自定义  ");
    switch (fcp.backcolor) {
      case 1:
        background1.setState(true);
        break;
      case 2:
        background2.setState(true);
        break;
      case 3:
        background3.setState(true);
        break;
    }
    background1.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        background1.setState(true);
        background2.setState(false);
        background3.setState(false);
        fcp.backcolor = 1;
        fcp.background = (new ImageIcon(FiveChessFrame.class
                .getResource("/res/background1.jpg"))).getImage();
        repaint();
      }
    });
    background2.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        background1.setState(false);
        background2.setState(true);
        background3.setState(false);
        fcp.backcolor = 2;
        fcp.background = (new ImageIcon(FiveChessFrame.class
                .getResource("/res/background2.jpg"))).getImage();
        repaint();
      }
    });
    background3.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        background1.setState(false);
        background2.setState(false);
        background3.setState(true);
        fcp.backcolor = 3;
        fcp.background = (new ImageIcon(FiveChessFrame.class
                .getResource("/res/background3.jpg"))).getImage();
        repaint();
      }
    });
    background_n.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        String path = new FileChooser().getPath();
        if (path != null) { // 如果是有效文件地址，则完成换背景操作
          background1.setState(false);
          background2.setState(false);
          background3.setState(false);
          fcp.background = (new ImageIcon(path)).getImage();
          fcp.backcolor = 4;
          repaint();

          File target = new File(
                  "E:\\data"), source = new File(
                  path);
          try { // 为避免图片删除导致背景失效，将图片拷贝到指定文件夹
            InputStream is = new FileInputStream(source);
            OutputStream os = new FileOutputStream(target);
            byte[] buf = new byte[1024];
            int len = 0;
            while ((len = is.read(buf)) != -1) {
              os.write(buf, 0, len);
            }
            is.close();
            os.close();
          } catch (FileNotFoundException e1) {
            e1.printStackTrace();
          } catch (IOException e2) {
            e2.printStackTrace();
          }
        }
      }
    });
    background.add(background1);
    background.add(background2);
    background.add(background3);
    background.add(background_n);
/**
 *  棋盘更换
 */
    JMenu chessboard = new JMenu("  棋盘  ");
    final JCheckBoxMenuItem chessboard1 = new JCheckBoxMenuItem("  黄色经典   ");
    final JCheckBoxMenuItem chessboard2 = new JCheckBoxMenuItem("  黑白朴素   ");
    final JCheckBoxMenuItem chessboard3 = new JCheckBoxMenuItem("  清爽怡人   ");
    final JMenuItem chessboard4 = new JMenuItem("  随机换装  ");
    switch (fcp.boardcolor) {
      case 1:
        chessboard1.setState(true);
        break;
      case 2:
        chessboard2.setState(true);
        break;
      case 3:
        chessboard3.setState(true);
        break;
    }
    chessboard1.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        chessboard1.setState(true);
        chessboard2.setState(false);
        chessboard3.setState(false);
        fcp.boardcolor = 1;
        fcp.chessboard = (new ImageIcon(FiveChessFrame.class
                .getResource("/res/chessboard1.jpg"))).getImage();
        repaint();
      }
    });
    chessboard2.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        chessboard1.setState(false);
        chessboard2.setState(true);
        chessboard3.setState(false);
        fcp.boardcolor = 2;
        fcp.chessboard = (new ImageIcon(FiveChessFrame.class
                .getResource("/res/chessboard2.jpg"))).getImage();
        repaint();
      }
    });
    chessboard3.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        chessboard1.setState(false);
        chessboard2.setState(false);
        chessboard3.setState(true);
        fcp.boardcolor = 3;
        fcp.chessboard = (new ImageIcon(FiveChessFrame.class
                .getResource("/res/chessboard3.jpg"))).getImage();
        repaint();
      }
    });
    chessboard4.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        chessboard1.setState(false);
        chessboard2.setState(false);
        chessboard3.setState(false);
        int n = (int) (Math.random() * 100) % 8 + 1; // 随机换棋盘，共八个供选择
        while (n == fcp.boardcolor)
          n = (int) (Math.random() * 100) % 8 + 1;
        fcp.boardcolor = n;
        fcp.chessboard = (new ImageIcon(FiveChessFrame.class
                .getResource("/res/chessboard" + n + ".jpg")))
                .getImage();
        repaint();
      }
    });
    chessboard.add(chessboard1);
    chessboard.add(chessboard2);
    chessboard.add(chessboard3);
    chessboard.add(chessboard4);
/**
 *  棋子更换
 */
    JMenu chess = new JMenu("  棋子  ");
    final JCheckBoxMenuItem chess1 = new JCheckBoxMenuItem("  经典黑   ");
    final JCheckBoxMenuItem chess2 = new JCheckBoxMenuItem("  玛瑙红   ");
    final JCheckBoxMenuItem chess3 = new JCheckBoxMenuItem("  水晶蓝   ");
    final JMenuItem chess4 = new JMenuItem("  随机换   ");
    switch (fcp.playerchessnum) {
      case 1:
        chess1.setState(true);
        break;
      case 2:
        chess2.setState(true);
        break;
      case 3:
        chess3.setState(true);
        break;
    }
    chess1.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        chess1.setState(true);
        chess2.setState(false);
        chess3.setState(false);
        fcp.playerchess = (new ImageIcon(FiveChessFrame.class
                .getResource("/res/chess1.png"))).getImage();
        fcp.chesschange(1);
        repaint();
      }
    });
    chess2.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        chess1.setState(false);
        chess2.setState(true);
        chess3.setState(false);
        fcp.playerchess = (new ImageIcon(FiveChessFrame.class
                .getResource("/res/chess2.png"))).getImage();
        fcp.chesschange(2);
        repaint();
      }
    });
    chess3.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        chess1.setState(false);
        chess2.setState(false);
        chess3.setState(true);
        fcp.playerchess = (new ImageIcon(FiveChessFrame.class
                .getResource("/res/chess3.png"))).getImage();
        fcp.chesschange(3);
        repaint();
      }
    });
    chess4.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        chess1.setState(false);
        chess2.setState(false);
        chess3.setState(false);
        int n = (int) (Math.random() * 10) % 8 + 1; // 随机换棋子，八个里选一个
        while (n == fcp.playerchessnum)
          n = (int) (Math.random() * 100) % 8 + 1;
        fcp.playerchess = (new ImageIcon(FiveChessFrame.class
                .getResource("/res/chess" + n + ".png"))).getImage();
        fcp.chesschange(n);
        repaint();
      }
    });
    chess.add(chess1);
    chess.add(chess2);
    chess.add(chess3);
    chess.add(chess4);

    saface.add(background);
    saface.add(chessboard);
    saface.add(chess);

    JMenu set = new JMenu("   设置    ");
/**
 *  背景音乐
 */
    JMenu music = new JMenu(" 背景音乐 ");
    final JCheckBoxMenuItem playmusic = new JCheckBoxMenuItem("  播放  ");
    final JCheckBoxMenuItem stopmusic = new JCheckBoxMenuItem("  停止  ");
    if (play)
      playmusic.setState(true);
    else
      stopmusic.setState(true);
    playmusic.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        playmusic.setState(true);
        stopmusic.setState(false);
        play = true;
        if (musicthread == null) { // 如果音乐线程未启动则启动
          try {
            sequencer = MidiSystem.getSequencer();
            sequencer.open();
          } catch (Exception e1) {
            e1.printStackTrace();
          }
          musicthread = new Thread(new MusicRun());
          musicthread.start();
        } else
          sequencer.start();
      }
    });
    stopmusic.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        playmusic.setState(false);
        stopmusic.setState(true);
        play = false;
        sequencer.stop(); // 关闭播放器，播放标志设置为false
      }
    });
    music.add(playmusic);
    music.add(stopmusic);
/**
 * 计分板
 */
    JMenu scoreboard = new JMenu("  计分板 ");
    final JCheckBoxMenuItem show = new JCheckBoxMenuItem("  显示  ");
    final JCheckBoxMenuItem hide = new JCheckBoxMenuItem("  隐藏  ");
    if (fcp.showscore)
      show.setState(true);
    else
      hide.setState(true);
    show.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        show.setState(true);
        hide.setState(false);
        fcp.showscore = true;
        repaint(); // 设置是否显示标志，重绘屏幕
      }
    });
    hide.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        show.setState(false);
        hide.setState(true);
        fcp.showscore = false;
        repaint();
      }
    });
    scoreboard.add(show);
    scoreboard.add(hide);
/**
 * 清空记录
 */
    JMenuItem clear = new JMenuItem("  清空记录 ");
    clear.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        fcp.win = 0;
        fcp.lose = 0;
        fcp.shenglv = 0;
        fcp.score = 0;
        fcp.repaint(); // 将输赢次数等信息清零，重绘屏幕
      }
    });
    set.add(music);
    set.add(scoreboard);
    set.add(clear);
/**
 * 帮助
 */
    JMenu help = new JMenu("   帮助   ");
    JMenuItem introduce = new JMenuItem("  游戏介绍 ");
    introduce.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        new HelpFrame();
      }
    });
    help.add(introduce);

    jm.add(model); // 将各个菜单加入菜单条
    jm.add(xianhou);
    jm.add(saface);
    jm.add(set);
    jm.add(help);

    this.setJMenuBar(jm);
  }

  /**
   * 加载各种图片素材
   */
  void readData() { // 必要加载素材
    fcp.huiqi0 = (new ImageIcon(
            FiveChessFrame.class.getResource("/res/huiqi0.png")))
            .getImage();
    fcp.huiqi1 = (new ImageIcon(
            FiveChessFrame.class.getResource("/res/huiqi1.png")))
            .getImage();
    fcp.zailai0 = (new ImageIcon(
            FiveChessFrame.class.getResource("/res/zailai0.png")))
            .getImage();
    fcp.zailai1 = (new ImageIcon(
            FiveChessFrame.class.getResource("/res/zailai1.png")))
            .getImage();
    fcp.smile = (new ImageIcon(
            FiveChessFrame.class.getResource("/res/smile.png"))).getImage();
    fcp.cry = (new ImageIcon(
            FiveChessFrame.class.getResource("/res/cry.png"))).getImage();
    fcp.rock = (new ImageIcon(
            FiveChessFrame.class.getResource("/res/rock.png"))).getImage();
    fcp.bomb1 = (new ImageIcon(
            FiveChessFrame.class.getResource("/res/bomb_1.gif")))
            .getImage();
    fcp.bomb2 = (new ImageIcon(
            FiveChessFrame.class.getResource("/res/bomb_2.gif")))
            .getImage();
    fcp.bomb3 = (new ImageIcon(
            FiveChessFrame.class.getResource("/res/bomb_3.gif")))
            .getImage();
    fcp.scoreboard = (new ImageIcon(
            FiveChessFrame.class.getResource("/res/scoreboard.png")))
            .getImage();


    // 根据你的设置选择背景,如果是自定义图片在制定目录里找到图片
    if (fcp.backcolor < 4)
      fcp.background = (new ImageIcon(
              FiveChessFrame.class.getResource("/res/background"
                      + fcp.backcolor + ".jpg"))).getImage();
    else
      fcp.background = (new ImageIcon(
              "E:\\data")).getImage();
    // 根据你的设置选择棋盘图片
    fcp.chessboard = (new ImageIcon(
            FiveChessFrame.class.getResource("/res/chessboard"
                    + fcp.boardcolor + ".jpg"))).getImage();
    // 根据你的设置选择你的棋子，定义1到9为你的棋子
    fcp.playerchess = (new ImageIcon(
            FiveChessFrame.class.getResource("/res/chess"
                    + fcp.playerchessnum + ".png"))).getImage();
    // 根据你的设置选择电脑的棋子
    fcp.computerchess = (new ImageIcon(
            FiveChessFrame.class.getResource("/res/chess"
                    + fcp.computerchessnum + ".png"))).getImage();

    int T = name.indexOf("的");
    String s = name.substring(0, T);
    data = new File("E:\\data\\" + s + ".txt"); // 根据路径找到这些文件
    data.getParentFile().mkdirs();
    if (!data.exists()) { // 如果记录文件不存在则创建
      try {
        data.createNewFile();
      } catch (IOException e) {
        e.printStackTrace();
      }
    } else { // 否则读取文件中的记录信息
      try { // 读取棋子数组
        DataInputStream ins = new DataInputStream(new FileInputStream(
                data));
        for (int i = 0; i < fcp.NUMBER; i++)
          for (int j = 0; j < fcp.NUMBER; j++) {
            fcp.chess[i][j] = ins.readInt();
          } // 读取各个变量
        play = ins.readBoolean();
        fcp.x = ins.readInt();
        fcp.y = ins.readInt();
        fcp.win = ins.readInt();
        fcp.lose = ins.readInt();
        fcp.shenglv = ins.readDouble();
        fcp.score = ins.readInt();
        fcp.count = ins.readInt();
        fcp.boardcolor = ins.readInt();
        fcp.backcolor = ins.readInt();
        fcp.playerchessnum = ins.readInt();
        fcp.computerchessnum = ins.readInt();
        fcp.canplay = ins.readBoolean();
        fcp.second = ins.readBoolean();
        fcp.iswin = ins.readBoolean();
        fcp.islose = ins.readBoolean();
        fcp.tompstone = ins.readBoolean();
        fcp.landmine = ins.readBoolean();
        fcp.showscore = ins.readBoolean();
        Stack<Integer> huiqitemp1 = new Stack<Integer>(); // 两个临时栈，用于倒置数据
        Stack<Integer> huiqitemp2 = new Stack<Integer>();
        while (true) { // 读取悔棋栈
          try {
            huiqitemp1.push(ins.readInt()); // 先写入临时栈，再写到系统栈
            huiqitemp2.push(ins.readInt());
          } catch (EOFException e) {
            break;
          }
        } // 将临时栈数据写入系统栈，恢复上次关闭时状态
        while (!huiqitemp1.empty()) {
          fcp.huiqiX.push(huiqitemp1.pop());
          fcp.huiqiY.push(huiqitemp2.pop());
        }
        ins.close();
      } catch (FileNotFoundException e) {
        e.printStackTrace();
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
  }

  /**
   * 播放音乐的内部类
   */
  // 播放音乐的内部类
  public class MusicRun implements Runnable {
    public void run() {
      while (true) {
        if (play) {
          try {
            num = (int) (Math.random() * 100) % 10; // 随机选择音乐，十选一
            sequence = MidiSystem.getSequence(FiveChessFrame.class
                    .getResource("/res/music" + num + ".mid"));
            sequencer.setSequence(sequence);
            sequencer.start();
            Thread.sleep(sequencer.getMicrosecondLength() / 1000);
          } catch (Exception e) {
            e.printStackTrace();
          }
        }
        try {
          Thread.sleep(2000); // 每2秒对线程进行检测，是否播放音乐
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    }
  }

  /**
   * 帮助类
   */
  // 显示帮助信息的内部类
  public class HelpFrame extends JFrame {
    private static final long serialVersionUID = 1L;

    public HelpFrame() {
      HelpPanel hp = new HelpPanel();
      this.add(hp);
      this.setLocation(350, 150);
      this.setSize(800, 500);
      this.setVisible(true);
      this.setResizable(false);
    }

    public class HelpPanel extends JPanel {
      private static final long serialVersionUID = 1L;

      public void paint(Graphics g) {
        Image help = (new ImageIcon(
                FiveChessFrame.class.getResource("/res/help.jpg")))
                .getImage();
        g.drawImage(help, 0, 0, 800, 500, this);
      }
    }
  }

  // WindowListener中没有实现的方法
  public void windowActivated(WindowEvent arg0) {
  }

  public void windowClosed(WindowEvent arg0) {
  }

  // 关闭窗口时，将数据写入文件
  public void windowClosing(WindowEvent arg0) {
    try {

      DataOutputStream ous = new DataOutputStream(new FileOutputStream(
              data));
      for (int k = 0; k < fcp.NUMBER; k++)
        for (int l = 0; l < fcp.NUMBER; l++) {
          ous.writeInt(fcp.chess[k][l]);
        }
      ous.writeBoolean(play);
      ous.writeInt(fcp.x);
      ous.writeInt(fcp.y);
      ous.writeInt(fcp.win);
      ous.writeInt(fcp.lose);
      ous.writeDouble(fcp.shenglv);
      ous.writeInt(fcp.score);
      ous.writeInt(fcp.count);
      ous.writeInt(fcp.boardcolor);
      ous.writeInt(fcp.backcolor);
      ous.writeInt(fcp.playerchessnum);
      ous.writeInt(fcp.computerchessnum);
      ous.writeBoolean(fcp.canplay);
      ous.writeBoolean(fcp.second);
      ous.writeBoolean(fcp.iswin);
      ous.writeBoolean(fcp.islose);
      ous.writeBoolean(fcp.tompstone);
      ous.writeBoolean(fcp.landmine);
      ous.writeBoolean(fcp.showscore);
      while (!fcp.huiqiX.empty()) { // 由于悔棋栈的长度不确定，放在最后写入，便于读出
        ous.writeInt(fcp.huiqiX.pop());
        ous.writeInt(fcp.huiqiY.pop());
      }
      ous.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  public void windowDeactivated(WindowEvent arg0) {
  }

  public void windowDeiconified(WindowEvent arg0) {
  }

  public void windowIconified(WindowEvent arg0) {
  }

  public void windowOpened(WindowEvent arg0) {
  }
}